/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */

/*
 * @Author:  João Pedro Martins Luis Nº5613 
 * @Curso:   Eng Informática Regime: Diurno
 * @Cadeira: Linguagens Programação 2ºANO -Segundo trabalho (C) Recurso
 * @Data:    14/07/2011
 */

/*
 * rebides.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sqlite3.h>
#include <Python.h>

#define N 100
#define NDOCENTES 100000

//Cabeçalhos dos metodos callbacks
static int callBackNumeroDocentes(int *** nrDocentes, int argc, char **argv, char **azColName);
static int callBackListaTitularesGrau(char*** lista, int argc, char **argv, char **azColName);
static int callBackListaEst(char*** lista, int argc, char **argv, char **azColName);
static int callBackcount(int*** nr, int argc, char **argv, char **azColName);




//metodo para escrever no ficheiro
void writeFile(char test[]);



/**
 * Metodo callBack do Número de Docentes 
 */
static int callBackNumeroDocentes(int *** nrDocentes, int argc, char **argv, char **azColName){
	**nrDocentes = atoi(argv[0] ? argv[0] : NULL);
	return 0;
}



/**
 * Metodo callback count, este metodo callback é utilizado
 * em várias consultas.
 */
static int callBackcount(int*** nr, int argc, char **argv, char **azColName){
	**nr = atoi(argv[0] ? argv[0] : NULL);
	return 0;
}

/*
 * Metodo que vai dar a estatistica com o numero total de docentes
 * por Grau, por Estabelecimento e por ano
 * recebe como parametro o ano
 * Este metodo faz três tipos de consulta a base de dados,
 * a primeira com o número de estabelecimentos num dado ano, a segunda 
 * a lista de estabelecimentos nesse mesmo ano, por fim a terceira 
 * que vai dar contar o numero total de docentes para cada 
 * estabelecimento com um determinado grau.
 * De referir ainda que este metodo faz a ordenação da lista dos estabelecimentos
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 */
int totalNrDocentesGrauEst(int ano)
{	
	int j, i, h;
	int** nr = malloc(sizeof(int));
	int** nrEstabelecimentos = malloc(sizeof(int));
	
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char nrDocentString[10];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "\nEstatistica do número total de Docentes por grau e por estabelecimento no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char listaGraus [3][20] = {"%licenci%","%mestre%","do%"};
	char listaGrausPrint [3][20] = {"licenciados","mestre","doutores"};
	char** first;
	char** lista;
	lista = (char**) malloc(1000 * sizeof(char*));

	for(j = 0; j < 1000; j++){
		lista[j] = (char*) malloc(200 * sizeof(char));
	}
	first = lista;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}

	//Numero de Estabelecimentos num dado ano
	char queryNrEstabelecimentos [100] = "SELECT count(DISTINCT (estabelecimento)) FROM registo_docentes WHERE ano = ";
	strcat(queryNrEstabelecimentos, anoString);
	rc = sqlite3_exec(db, queryNrEstabelecimentos, callBackcount, &nrEstabelecimentos, &zErrMsg);
	if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
	}
	//Fim da query do numero de estabelecimentos num dado ano
	
	// Lista de estabelecimentos
	char query[80] = "SELECT DISTINCT (estabelecimento), ano FROM registo_docentes WHERE ano = ";
	strcat(query, anoString);
	rc = sqlite3_exec(db, query, callBackListaEst, &lista, &zErrMsg);
	if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
	}
	//ordenação da lista de estabelecimentos
	qsort(lista, (*nrEstabelecimentos), sizeof(char *), strcmp  );
	//FIM da Lista de Estabelecimentos 

	for(i =0; i < ((int)(*nrEstabelecimentos)); i++)
	{	
		for (h = 0 ; h < 3; h++)
		{
			//Query que calcula o numero total de docentes por grau e 
			//por tipo de estabelecimento e por ano
			char TGrau[23];
			char estabelLike[30] = " AND estabelecimento LIKE ";
			char estabelecimento[100];
			char andAno [12] = " AND ano = ";
			char queryNrDocentes[400] = "SELECT count(DISTINCT docente) as Docentes from registo_docentes WHERE grau LIKE ";
			sprintf(anoString, "%d", ano);
			sprintf(TGrau, "'%s'", listaGraus[h]);
			strcat(queryNrDocentes, TGrau);
			strcat(queryNrDocentes, estabelLike);
			sprintf(estabelecimento, "'%s'", *first);
			strcat(queryNrDocentes,estabelecimento);
			strcat(queryNrDocentes,andAno);
			strcat(queryNrDocentes,anoString);
			rc = sqlite3_exec(db, queryNrDocentes, callBackcount, &nr, &zErrMsg);
			if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
			}
			printf("Número total de docentes com o grau %s, no estabelecimento %s no ano 200%d = %d\n"
			   		, listaGrausPrint[h], *first, ano, ((int)*nr));
			//escrever no ficheiro
			char testoFicheiro[300] = "Número total de docentes com o grau ";
			strcat(testoFicheiro, listaGrausPrint[h]);
			strcat(testoFicheiro, " no estabelecimento ");
			strcat(testoFicheiro, estabelecimento);
			strcat(testoFicheiro, " no ano 200");
			strcat(testoFicheiro, anoString);
			strcat(testoFicheiro, " é igual a ");
			sprintf(nrDocentString, "%d", ((int)*nr));
			strcat(testoFicheiro, nrDocentString);
			writeFile(testoFicheiro);
			//FIM escrever no ficheiro
		}
		first++;
	}
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);
	
	free(nrEstabelecimentos);
	free(nr);
	return (0);
}



/**
 * Metodo callBack da lista dos tipos de estabelecimento 
 */
static int callBackListaTipEst(char*** lista, int argc, char **argv, char **azColName){
	int i;
	for(i=0; i<argc; i++){
		if(i == 0){
			sprintf(**lista, "%s", argv[0]);
			(*lista)++;		
		}
    }
    return 0;
}



/**
 * Metodo callback Lista dos estabelecimentos em cada ano
 */
static int callBackListaEst(char*** lista, int argc, char **argv, char **azColName){
	int i;
	for(i=0; i<argc; i++){
		if(i == 0){
			sprintf(**lista, "%s", argv[0]);
			(*lista)++;
		}
    }
    return 0;
}




/**
 * Metodo Callback da Lista dos titulares de cada grau
 */
static int callBackListaTitularesGrau(char*** lista, int argc, char **argv, char **azColName){
	int i;
	for(i=0; i<argc; i++){
		if(i == 0){
			//printf("%s\n", argv[0]);
			sprintf(**lista, "%s", argv[0]);
			
			(*lista)++;		
		}
    }
    return 0;
}

/**
 * Metodo que vai dar a lista dos titulares dos 
 * graus (Licenciados, Mestres e doutores) num dado ano,
 * recebe como parametro o ano
 * Este metodo faz dois tipos de consulta a base de dados,
 * a primeira com o número de docentes por grau num dado ano e a segunda 
 * a lista de docentes dos titulares dos graus nesse mesmo ano.
 * De referir ainda que este metodo faz a ordenação da lista dos titulares dos graus
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 * Importa ainda referir que este metodo só faz a contagem e a lista
 * dos docentes com os seguintes graus Licenciados, Mestres e Doutoures.
 */
int listaTitularesGrau(int ano)
{
	int i, j, h;
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char contString[4];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "Estatistica Lista dos Titulares dos graus no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char** first;
	char** lista;
	int** nrDocentesG;
	nrDocentesG = malloc(sizeof(int));

	char listaGraus [3][20] = {"%licenci%","%mestre%","do%"};
	char listaGrausPrint [3][20] = {"licenciado","mestre","doutor"};

	lista = (char**) malloc(NDOCENTES * sizeof(char*));

	for(j = 0; j < NDOCENTES; j++){
		lista[j] = (char*) malloc(300 * sizeof(char));
	}

	first = lista;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	for(h = 0; h < 3; h ++)
	{
		//query que conta o numero de docentes por grau
		char queryCountNrDocentGrau[200] = "SELECT count(DISTINCT docente) as Docentes FROM registo_docentes WHERE grau LIKE ";
		char grauLicenciado[23];
		char andAno [12] = " AND ano = ";
		sprintf(grauLicenciado, "'%s'", listaGraus[h]);
		strcat(queryCountNrDocentGrau, grauLicenciado);
		strcat(queryCountNrDocentGrau, andAno);
		strcat(queryCountNrDocentGrau,anoString);
		//printf("%s\n", queryCountNrDocentGrau);
		rc = sqlite3_exec(db, queryCountNrDocentGrau, callBackNumeroDocentes, &nrDocentesG, &zErrMsg);
		if( rc!=SQLITE_OK ){
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
		//FIM

		//printf("docentes %d\n", *nrDocentesG);
		lista = first;
		char TGrau[23];
		char queryListaTitularesGraus[250] = "SELECT DISTINCT (docente) as Docentes FROM registo_docentes WHERE grau LIKE ";
		sprintf(anoString, "%d", ano);
		sprintf(TGrau, "'%s'", listaGraus[h]);
		strcat(queryListaTitularesGraus, TGrau);
		strcat(queryListaTitularesGraus,andAno);
		strcat(queryListaTitularesGraus,anoString);
		rc = sqlite3_exec(db, queryListaTitularesGraus, callBackListaTitularesGrau, &lista, &zErrMsg);
		if( rc!=SQLITE_OK ){
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
		//ordenação da lista dos titulares dos graus
		qsort(lista, (*nrDocentesG), sizeof(char *), strcmp  );
		printf("\n");
		for(i =0; i < ((int)(*nrDocentesG)) ; i++){
			printf("%d) Ano 200%d -> docente %s -> grau %s\n", i, ano,
			   		*first, listaGrausPrint[h]);
			//escrever no ficheiro
			char testoFicheiro[300] = "";
			sprintf(contString, "%d", i);
			strcat(testoFicheiro, contString);
			strcat(testoFicheiro, ") ");
			strcat(testoFicheiro, (*first));
			strcat(testoFicheiro, " - ");
			strcat(testoFicheiro, listaGrausPrint[h]);
			writeFile(testoFicheiro);
			//FIM escrever no ficheiro
			first++;
		}
	}
	//fecha a Base Dados (BaseDadosrebides.db)
		sqlite3_close(db);
	
	/*for(j=0; j < NDOCENTES; j++){
		free(first[j]);
	}*/
	//free(first);
	free(nrDocentesG);
	return(0);
}





/**
 * Metodo para escrever as estatisticas e 
 * as listas num ficheiro com o nome
 * Statistics.html
 * Recebe como parametro a mensagem
 * a escrever no ficheiro.
 * Importa referir que cada vez que este metodo 
 * é chamado é feito um append ao ficheiro, 
 * "file = fopen("Statistics.html","a+");"
 */
void writeFile(char mensagem[])
{
	FILE *file; 
	file = fopen("Statistics.html","a+");		
	fprintf(file, "%s", mensagem);
	fprintf(file, "%s", "<p>");
	fclose(file);
}